package com.iplant.base.utils;

import com.iplant.base.controller.BaseController;
import com.iplant.base.po.BasePO;
import com.iplant.base.utils.annotation.dao.DBBaseDAO;
import com.iplant.base.utils.annotation.po.DBBasePO;
import com.iplant.base.utils.cache.CacheUtils;
import com.iplant.base.utils.log.TraceLoggerTool;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.base.utils.sql.orm.POUtils;
import com.iplant.base.utils.sql.orm.PoServiceImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

@Component
public class ApplicationContextBase implements ApplicationContextAware, ApplicationRunner {

    private ApplicationContext applicationContext;

    private RequestMappingHandlerMapping handerMapping;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        handerMapping=applicationContext.getBean(RequestMappingHandlerMapping.class);



        TraceLoggerTool.SetAPIMap(handerMapping.getHandlerMethods());

        //将DBBasePO获取到缓存中
        Set<Class<?>> annotatedClasses = this.findAnnotatedClasses("com.iplant", DBBasePO.class);

        if(annotatedClasses!=null&&annotatedClasses.size()>0){

            for (Class<?> beanClass : annotatedClasses) {
                if (BasePO.class.isAssignableFrom(beanClass) && !BasePO.class.equals(beanClass)) {

                    DBBasePO wDBBasePO = POUtils.GetInstance().getDBBasePO(beanClass);
                    if(wDBBasePO==null)
                        continue;

                    BaseController.BasePOClassMap.put(beanClass.getSimpleName(),(Class<? extends BasePO>) beanClass);

                    if(wDBBasePO.Cache()){
                        CacheUtils.Cache((Class<? extends BasePO>) beanClass);
                    }
                }
            }
        }


        //将DBBaseDAO获取到缓存中
        annotatedClasses = this.findAnnotatedClasses("com.iplant", DBBaseDAO.class);

        if(annotatedClasses!=null&&annotatedClasses.size()>0){

            Class<? extends BasePO> wPOClazz = null;
            for (Class<?> beanClass : annotatedClasses) {
                if (BaseDAO.class.isAssignableFrom(beanClass) && !BaseDAO.class.equals(beanClass)) {

                    wPOClazz= POUtils.GetInstance().getDBBaseDAOClass(beanClass);
                    if(wPOClazz==null)
                        continue;
                    PoServiceImpl.BaseDAOClassMap.put(wPOClazz, (Class<? extends BaseDAO>)beanClass);
                }
            }
        }

    }

    private Set<Class<?>> findAnnotatedClasses(String basePackage, Class<? extends Annotation> annotation) {
        Set<Class<?>> annotatedClasses = new HashSet<>();
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);

        // 添加过滤器，以便只扫描包含指定注解的类
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotation));

        // 扫描指定包及其子包中的类
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents(basePackage)) {
            try {
                annotatedClasses.add(Class.forName(beanDefinition.getBeanClassName()));
            } catch (ClassNotFoundException e) {
                // 处理异常
            }
        }

        return annotatedClasses;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext=applicationContext;
    }
}
